package cn.schoolwow.workflow.module.definition.action.flow;

import cn.schoolwow.quickdao.domain.DAO;
import cn.schoolwow.quickdao.domain.transaction.Transaction;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.check.instanceList.CheckInstanceList;
import cn.schoolwow.util.domain.query.instanceList.QueryInstanceList;
import cn.schoolwow.workflow.domain.deploy.WorkFlowDeployJumpFilterCondition;
import cn.schoolwow.workflow.domain.deploy.WorkFlowDeployRequest;
import cn.schoolwow.workflow.entity.WorkFlowDefinition;
import cn.schoolwow.workflow.entity.WorkFlowNode;
import cn.schoolwow.workflow.entity.WorkFlowNodeJump;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.Validate;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class InsertWorkFlowDefinitionFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        DAO dao = flowContext.checkInstanceData(DAO.class);

        dao.startTransaction(transaction -> {
            flowContext.putCurrentFlowInstanceData(transaction, Transaction.class);
            insertWorkFlowDefinition(flowContext);
            insertWorkFlowNodeFlow(flowContext);
            insertWorkFlowJumpFlow(flowContext);
        });
    }

    @Override
    public String name() {
        return "插入工作流定义记录";
    }

    private void insertWorkFlowDefinition(FlowContext flowContext){
        WorkFlowDeployRequest workFlowDeployRequest = flowContext.checkInstanceData(WorkFlowDeployRequest.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);

        transaction.addRecordString("部署工作流-插入工作流定义信息");
        WorkFlowDefinition workFlowDefinition = new WorkFlowDefinition();
        workFlowDefinition.setName(workFlowDeployRequest.name);
        if(null!=workFlowDeployRequest.workFlowDefinitionOption){
            workFlowDefinition.setOption(JSON.parseObject(JSON.toJSONString(workFlowDeployRequest.workFlowDefinitionOption)));
        }
        transaction.insert(workFlowDefinition);
        Validate.isTrue(workFlowDefinition.getId()>0, "获取工作流定义自增id失败");
        flowContext.putCurrentCompositeFlowData("workFlowDefinitionId", workFlowDefinition.getId());
    }

    private void insertWorkFlowNodeFlow(FlowContext flowContext){
        JSONObject workflow = flowContext.checkData("workflow", JSONObject.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);
        long workFlowDefinitionId = flowContext.checkData("workFlowDefinitionId", long.class);

        List<WorkFlowNode> workFlowNodeList = new ArrayList<>();
        JSONArray nodes = workflow.getJSONArray("nodes");
        for(int i=0;i<nodes.size();i++){
            JSONObject node = nodes.getJSONObject(i);

            WorkFlowNode workFlowNode = node.toJavaObject(WorkFlowNode.class);
            workFlowNode.setDefinitionId(workFlowDefinitionId);
            workFlowNodeList.add(workFlowNode);
        }
        transaction.addRecordString("部署工作流-插入工作流节点定义信息");
        transaction.insert(workFlowNodeList);
        flowContext.putCurrentCompositeFlowData("workFlowNodeList", workFlowNodeList);
    }

    private void insertWorkFlowJumpFlow(FlowContext flowContext){
        JSONObject workflow = flowContext.checkData("workflow", JSONObject.class);
        Transaction transaction = flowContext.checkInstanceData(Transaction.class);
        List<WorkFlowNode> workFlowNodeList = flowContext.checkData("workFlowNodeList", List.class);
        long workFlowDefinitionId = flowContext.checkData("workFlowDefinitionId", long.class);

        List<WorkFlowNodeJump> workFlowNodeJumpList = new ArrayList<>();
        JSONArray jumpArray = workflow.getJSONArray("jumpArray");
        for(int i=0;i<jumpArray.size();i++){
            JSONObject jump = jumpArray.getJSONObject(i);
            WorkFlowNodeJump workFlowNodeJump = new WorkFlowNodeJump();
            workFlowNodeJump.setDefinitionId(workFlowDefinitionId);
            workFlowNodeJump.setJumpName(jump.getString("jumpName"));
            {
                String current = jump.getString("current");
                WorkFlowNode workFlowNode = QueryInstanceList.newQuery(workFlowNodeList)
                        .addQuery("name", current)
                        .execute()
                        .getOne();

                Validate.notNull(workFlowNode, "跳转节点不存在!节点名称:"+current);
                workFlowNodeJump.setCurrentNodeId(workFlowNode.getId());
            }
            {
                String next = jump.getString("next");
                WorkFlowNode workFlowNode = QueryInstanceList.newQuery(workFlowNodeList)
                        .addQuery("name", next)
                        .execute()
                        .getOne();
                Validate.notNull(workFlowNode, "跳转节点不存在!节点名称:"+next);
                workFlowNodeJump.setNextNodeId(workFlowNode.getId());
            }
            workFlowNodeJump.setCondition(jump.getInteger("condition"));
            JSONArray filterConditionList = jump.getJSONArray("filterCondition");
            workFlowNodeJump.setFilterCondition(filterConditionList);
            workFlowNodeJump.setPriorityLevel(jump.getInteger("priorityLevel"));
            if(null!=filterConditionList){
                for(int j=0;j<filterConditionList.size();j++){
                    List<WorkFlowDeployJumpFilterCondition> workFlowDeployJumpFilterConditionList = filterConditionList.getJSONArray(j).toJavaList(WorkFlowDeployJumpFilterCondition.class);
                    CheckInstanceList.newCheck(workFlowDeployJumpFilterConditionList)
                            .notEmptyCheck("field", "过滤条件字段名称")
                            .notEmptyCheck("operator", "过滤条件操作符")
                            .notEmptyCheck("value", "过滤条件字段值")
                            .inValueCheck("operator", Arrays.asList(">",">=","<","<=","=","包含"), "过滤条件操作符");
                }
            }
            workFlowNodeJumpList.add(workFlowNodeJump);
        }
        transaction.addRecordString("部署工作流-插入工作流节点跳转信息");
        transaction.insert(workFlowNodeJumpList);
        flowContext.putCurrentCompositeFlowData("workFlowNodeJumpList", workFlowNodeJumpList);
    }
}
